#include "shell_functions.h"

char binstr[MAXLINE] = "/bin/";

int run_shell() 
{ 
  commandLine cmd = NULL;
  
  char buffer[MAXLINE];
  char * input;
  
    
while(TRUE) 
{
  printf("fatalblueshell> ");
  input = fgets(buffer,MAXLINE,stdin);
  if (input != NULL)
    {
        char * lf = strchr(buffer, '\n'); // On cherche le caractere '\n'
        
        if (lf != NULL) // S'il est present, ... 
            *lf = '\0'; // ... on le supprime   
    }
  if( strcmp(input,"exit") == 0 ) break;
  cmd = analyseCommandLine(input);
  fork_process(cmd);
}
   
  /* Test sans le prompt */
  //cmd = analyseCommandLine("ls -l --sort=size | grep shell | grep test | grep c");
  //fork_process(cmd);
  
  /* On free la commandLine */
  while(cmd != NULL) cmd = deleteElement(cmd);
  
  return 0;
}

int fork_process(commandLine cmd)
{
  int status;
  int filedes[2]; /* [0]=reading [1]=writing */
  pid_t pid_fils, pid_filsn;

/************ CHILD 1 *************/
  if((pid_fils=fork()) == 0) 
  {
    if(cmd->pipe == TRUE) 
    {        
      /* Creation de la pipe */
      if(pipe(filedes)==-1) {
        perror("pipe");
        exit(-1); }
      
      /* On va fork() un nouveau process si besoin est, et récuperer son pid pour que le père puisse l'attendre */
      if(cmd->nxt != NULL) {
        pid_filsn = fork_process_recur(cmd->nxt,filedes);
        pid_fils = pid_filsn; }
      
      /* On redirige stdout vers la writing pipe */
      if(dup2(filedes[1],STDOUT_FILENO)==-1) {
        perror("dup");
        exit(-1); }
   
      /* On close la pipe en écriture dans tous les cas */
      if(close(filedes[1])==-1) { 
        perror("close 1");
        exit(-1); }
      
      /* On close la pipe de lecture */
      if(close(filedes[0])==-1) {
        perror("close 0");
        exit(-1); }
    }
    
    /* On execute cmd, /!\ execve does not return on success */
    strcat(binstr,cmd->arg[0]);   
    execve(binstr,cmd->arg,NULL);
      perror("exec");
      exit(-1);
      
  }

/************ PARENT **************/
  else 
  { 
    /* le père attend l'execution du dernier fils */
    waitpid(pid_fils,&status,0);
  }
  
  return 0;
}


pid_t fork_process_recur(commandLine cmd,int filedes[2])  
{  
  pid_t mypid, pid_next;
  int new_fd[2];
  
  /************ CHILD n+1 *************/
  if((mypid=fork()) == 0) 
  {
    /* On redirige stdin vers la reading pipe */
    if(dup2(filedes[0],STDIN_FILENO)==-1) {
      perror("dup");
      exit(-1); }
      
    /* On close la pipe en lecture */
    if(close(filedes[0])==-1) {
      perror("close 0");
      exit(-1); }
    
    /* On close la pipe en écriture */
    if(close(filedes[1])==-1) { 
      perror("close 1");
      exit(-1); }
    
    /* On va fork() un nouveau process si besoin est, et récuperer son pid pour que le père puisse l'attendre */
    if(cmd->pipe == TRUE) 
    {
     /* Creation de la nouvelle pipe */
      if(pipe(new_fd)==-1) {
        perror("pipe");
        exit(-1); }
      
      if(cmd->nxt != NULL) {
        pid_next = fork_process_recur(cmd->nxt,new_fd);
        mypid = pid_next; }
      
      /* On redirige stdout vers la nouvelle writing pipe */
      if(dup2(new_fd[1],STDOUT_FILENO)==-1) {
          perror("dup");
          exit(-1); }
          
      /* On close la nouvelle pipe en lecture */
      if(close(new_fd[0])==-1) {
        perror("close 0");
        exit(-1); }
    
      /* On close la nouvelle pipe en écriture */
      if(close(new_fd[1])==-1) { 
        perror("close 1");
        exit(-1); }
   }
    
    /* On execute cmd, qui prend comme entrée la sortie de child1 */
    strcat(binstr,cmd->arg[0]);
    printf("*** %s *** %s ***\n",cmd->arg[0],cmd->arg[1]);     
    execve(binstr,cmd->arg,NULL);
      perror("exec");
      exit(-1);
  }
  return mypid;
}
